﻿using System;

namespace Mojo.Widgets
{
    /// <summary>
    /// &lt;div x-mojo-element="List" id="listId" class="listClass" name="listName"&gt;&lt;/div&gt;
    /// </summary>
    public class List
    {
        //TODO:focusItem	 itemModel, focusSelector	 Focus the item designated by the item model; optionally pass in the focusSelector to focus a specific element within the item.
        //TODO:getItemByNode	 node	 Returns the item model associated with the list item containing the given node, if any. Returns undefined if not.
        /// <summary>
        /// Returns the current length of the list.
        /// </summary>
        /// <returns></returns>
        public int GetLength()
        {
            return 0;
        }

        /// <summary>
        /// Call to set the overall length of the list. This function will set the limit on what range of items may be requested, but will generally not invalidate any existing items or request any new ones. It MAY request new items when the currently loaded items window is either not full, or the length change causes the items window to move. The latter case can occur if the length change causes the window to be "out of bounds", or if it would ideally be positioned past the end of the list.
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public void SetLength(int length)
        {
        }

        /// <summary>
        /// Behaves like setLength, except that all currently loaded items are invalidated. For lazily loaded lists, this API will result in a request for a whole window of items. Note that items are invalidated even when the length of the list does not actually change.
        /// </summary>
        /// <param name="length"></param>
        public void SetLengthAndInvalidate(int length)
        {
        }

        //TODO:getLoadedItemRange		 Returns a hash with offset & limit properties indicating the range of currently loaded item models (or items which have been requested). This is sometimes used on the service side to optimize subscription data.

        /// <summary>
        /// Returns the maximum number of loaded items the list will maintain in its local cache. Function has no affect when the list size != 0.
        /// </summary>
        /// <returns></returns>
        public int GetMaxLoadedItems()
        {
            return 0;
        }

        //TODO:getNodeByIndex	 index	 Return top level node for the list item of the given index. Returns undefined if the item does not exist or is not currently rendered.

        /// <summary>
        /// Causes the given items to be reloaded (if currently loaded). If limit is unspecified, causes all items after 'offset' to be invalidated.
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="limit"></param>
        public void InvalidateItems(int offset, int? limit)
        {
        }

        /// <summary>
        /// Inserts the given array of items into the list at the given offset.If list items are dynamically loaded, this may cause some to be kicked out of the cache. Calling this API will not cause a property-change event to be fired.
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="items"></param>
        public void NoticeAddedItems(int offset, object[] items)
        {
        }

        /// <summary>
        /// Removes items from the list beginning at the given offset, and continuing for 'limit' items. If list items are dynamically loaded, this may cause new ones to be requested. Calling this API will not cause a property-change event to be fired.
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="limit"></param>
        public void NoticeRemovedItems(int offset, int limit)
        {
        }

        /// <summary>
        /// Causes the given items to be replaced and re-rendered. Items provided past the current end of the list will cause the length to grow. MUST pass an array.        
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="items"></param>
        public void NoticeUpdatedItems(int offset, object[] items)
        {
        }

        /// <summary>
        /// Attempts to scroll the scene to reveal the item with the given index. May behave poorly when working with variable height list items which are not currently loaded, since we can't accurately predict the height of the final rendered content.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="animate"></param>
        public void RevealItem(int index, bool animate)
        {
        }

        /// <summary>
        /// Shows the "add item" in the list.
        /// </summary>
        /// <param name="show"></param>
        public void ShowAddItem(bool show)
        {
        }
    }

    public class ListAttributes : WidgetsCreateAttributes
    {
        /// <summary>
        /// If defined, a special "add" item will be appended to the list and taps on this item will generate a "Mojo.Event.listAdd" event. The string is used to label the entry. If null, then it will default to "+Add".
        /// </summary>
        public string AddItemLabel;

        /// <summary>
        /// If false, delete swipes will post a "delete/undo" button pair. If true, deletes will be made immediately after swiping.
        /// </summary>
        public bool AutoconfirmDelete;

        /// <summary>
        /// Name of the item object property in which to store the deleted status of an item.
        /// </summary>
        public string DeletedProperty;

        //TODO:dividerFunction	 Function	 No		 Function to create divider elements.
        //TODO:dividerTemplate	 Function	 No	 list-divider	 Function to format a divider.         

        /// <summary>
        /// Used for drag&drop reordering. If specified, will allow items to be dragged from one list to another of the same data type.
        /// </summary>
        public string DragDatatype;

        /// <summary>
        /// File path relative to the app folder for template for empty list; this is only implemented for lists loaded via the itemsCallback property.
        /// </summary>
        public string EmptyTemplate;

        /// <summary>
        /// If true, list widget will apply optimizations for fixed height items.
        /// </summary>
        public bool FixedHeightItems;

        //TODO:formatters	 Function	 No		 Object functions to format list entries based on model properties.         

        /// <summary>
        /// Specify true for this if the list has no child widgets; allows for faster processing of simple lists; in versions of the List widget where this property does not exist, behavior will be as if hasNoWidgets was set to false.
        /// </summary>
        public bool HasNoWidgets;

        /// <summary>
        /// Initial value used for average height estimation.
        /// </summary>
        public int InitialAverageRowHeight;

        //TODO:itemsCallback	 Function	 No	 none	 Items will be loaded as needed by calling this function of the form: callback(widget, offset, count)


        /// <summary>
        /// Model property for the items list.
        /// </summary>
        public string ItemsProperty;

        /// <summary>
        /// File path relative to the app folder for the item template.
        /// </summary>
        public string ItemTemplate;

        /// <summary>
        /// File path relative to the app folder for the container template. The container template must contain #{-listElements} or not items will be rendered.
        /// </summary>
        public string ListTemplate;

        /// <summary>
        /// Number of items to fetch ahead when loading new items.
        /// </summary>
        public int Lookahead;

        /// <summary>
        /// File path relative to app folder for template for items that are rendered before loading.
        /// </summary>
        public string NullItemTemplate;

        /*
onItemRendered	 Function	 No	 none	 Called each time an item is rendered into the DOM with these arguments: (listWidget, itemModel, itemNode)
         */

        /// <summary>
        /// If specified, the item models will be checked for this property, and swipeToDelete will be ignored on that item if the item model's property is truthy.
        /// </summary>
        public string PreventDeleteProperty;

        /// <summary>
        /// Max number of items to render at once; increase this if the UI overruns the list boundaries.
        /// </summary>
        public int RenderLimit;

        /// <summary>
        /// If true, list entries can be reordered by drag and drop.
        /// </summary>
        public bool Reorderable;

        /// <summary>
        /// If true, list entries can be deleted with a swipe.
        /// </summary>
        public bool SwipeToDelete;

        /// <summary>
        /// Name of an item model property which can be used to uniquely identify items. If specified, List will maintain a hash of swiped items instead of setting a deleted property, preventing the app from having to persist the deleted property.
        /// </summary>
        public string UniquenessProperty;
    }

    public class ListModel : WidgetsCreateModel
    {
        /// <summary>
        /// A list of objects to display in the list. Required unless the itemsCallback property is set as an Attribute property.
        /// </summary>
        public object[] Items;

        /// <summary>
        /// Model property name for disabled.
        /// </summary>
        public bool Disabled;

        /// <summary>
        ///  Model property name for label.
        /// </summary>
        public string Label;
    }
}
